"""
Case Type   : 极致RTO支持备机可读
Case Name   : 资源池化存储复制双集群，主集群创建普通行存段页式表(结合tpcc)，备集群开启极致RTO场景下验证备机可读
Create At   : 2025/03
Owner       : haomeng
Description :
    1、备集群内开启极致RTO特性，重启使其生效
    2、利用tpcc业务模型，创建行存段页式表，导入数据
    3、备集群首备节点查看表数据
    4、备集群从备节点查看表数据
    5、清理环境，恢复环境初始状态
Expect      :
    1、设置成功，重启成功
    2、创建成功，导入数据成功
    3、查看成功，与主集群内查看数据一致
    4、查看失败，从备节点不可读
    5、清理成功，恢复环境成功
History     :
"""

import os
import time
import unittest

from testcase.utils.Common import Common
from testcase.utils.CommonSH import CommonSH
from testcase.utils.Constant import Constant
from testcase.utils.Logger import Logger
from yat.test import Node
from yat.test import macro

class RTOStandbyRead(unittest.TestCase):

    def setUp(self):
        self.log = Logger()
        self.log.info(f'----{os.path.basename(__file__)} start----')
        self.root_user = Node(node='PrimaryRoot')
        self.p_pri_sh = CommonSH('P_PrimaryDbUser')
        self.s_pri_sh = CommonSH('S_PrimaryDbUser')
        self.s_sta_sh = CommonSH('S_Standby1DbUser')
        self.com = Common()
        self.constant = Constant()

        self.param_list = ['recovery_parse_workers', 'recovery_redo_workers', 'ss_disaster_mode']
        self.value_list = ['4', '4']
        self.default_value = []
        self.table_list = ['bmsql_config', 'bmsql_customer', 'bmsql_district', 'bmsql_history',
                           'bmsql_item', 'bmsql_new_order', 'bmsql_oorder', 'bmsql_order_line',
                           'bmsql_stock', 'bmsql_warehouse']

        self.log.info('---校验当前环境是否为存储复制双集群---')
        mode = self.p_pri_sh.execut_db_sql(f'show {self.param_list[2]};')
        self.log.info(mode)
        self.assertIn('dorado', mode, '当前环境不是存储复制双集群')

    def test_rto_standby_read(self):
        text = '-----step1:备集群内开启极致RTO特性，重启使其生效;  expect:设置成功，重启成功-----'
        self.log.info(text)

        for param in self.param_list[:2]:
            value = self.s_pri_sh.execut_db_sql(f'show {param}')
            self.default_value.append(value.splitlines()[-2].strip())
        self.log.info(self.default_value)

        for param in self.param_list[:2]:
            set_param = self.s_pri_sh.execute_gsguc('set',
                                                    self.constant.GSGUC_SUCCESS_MSG,
                                                    f'{param} = {self.value_list[self.param_list.index(param)]}')
            self.log.info(set_param)
            self.assertTrue(set_param, '参数设置失败')

        self.log.info('---重启集群使参数生效---')
        restart = self.s_sta_sh.restart_db_cluster()
        self.log.info(restart)
        self.assertTrue(restart, '集群重启失败')

        self.log.info('---查看参数值修改是否成功---')
        for param in self.param_list[:2]:
            value = self.s_pri_sh.execut_db_sql(f'show {param};')
            self.assertEqual(value.splitlines()[-2].strip(),
                             self.value_list[self.param_list.index(param)], '参数未修改成功')

        text = '-----step2:主集群内执行tpcc读写业务  expect:业务执行成功-----'
        self.log.info(text)

        tpcc_cmd = f'./runBenchmark.sh {macro.PROPS_FILENAME}'
        self.log.info(tpcc_cmd)

        tpcc_execute = self.com.start_tpcc(self.root_user, f'{macro.TPCC_PATH}', tpcc_cmd)
        self.log.info(tpcc_execute)
        self.assertIn('Session End', tpcc_execute, 'tpcc执行失败')

        text = '-----step3:备集群内首备节点查看表数据  expect:与主集群内查看数据一致-----'
        self.log.info(text)

        self.log.info('---等待备集群数据同步---')
        flag = self.s_pri_sh.check_data_consistency()
        self.assertTrue(flag, '数据同步失败')

        sta_res_list = []
        for table in self.table_list:
            sta_sql = f"select count(*) from {table};"
            self.log.info(sta_sql)
            sta_res = self.s_pri_sh.execut_db_sql(sta_sql)
            self.log.info(sta_res)
            sta_res_list.append(sta_res)
            self.assertNotIn('(0 rows)', sta_res, '查询结果异常')
        self.log.info('-----备集群数据结果-----')
        self.log.info(sta_res_list)

        self.log.info('-----对比主备集群数据一致性  expect:查看成功，与主集群数据一致-----')
        pri_res_list = []
        for table in self.table_list:
            sql = f"select count(*) from {table};"
            self.log.info(sql)
            pri_res = self.p_pri_sh.execut_db_sql(sql)
            self.log.info(pri_res)
            pri_res_list.append(pri_res)
            self.assertNotIn('(0 rows)', pri_res, '查询结果异常')
        self.log.info('-----主集群数据结果-----')
        self.log.info(pri_res_list)

        time.sleep(5)
        self.assertEqual(pri_res_list, sta_res_list, '主备查询结果不一致')

        text = '-----step4:备集群内从备节点查看表数据  expect:从备节点不可读-----'
        self.log.info(text)

        ss_select = self.s_sta_sh.execut_db_sql('select count(*) from bmsql_config;')
        self.log.info(ss_select)
        self.assertIn(self.constant.disaster_read_fail_msg, ss_select, '从备节点查询成功')

    def tearDown(self):
        text = '-----step5:清理环境，恢复环境初始状态  expect:清理成功，恢复环境成功-----'
        self.log.info(text)

        for param in self.param_list[:2]:
            reset_param = self.s_pri_sh.execute_gsguc('set',
                                                      self.constant.GSGUC_SUCCESS_MSG,
                                                      f'{param} = {self.default_value[self.param_list.index(param)]}')
            self.log.info(reset_param)

        restart = self.s_pri_sh.restart_db_cluster(False)
        self.log.info(restart)

        for param in self.param_list[:2]:
            reset_value = self.s_pri_sh.execut_db_sql(f'show {param};')
            self.log.info(reset_value)
            self.assertEqual(reset_value.splitlines()[-2].strip(),
                             self.default_value[self.param_list.index(param)], '参数恢复失败')
        self.log.info(f'----{os.path.basename(__file__)} end----')
